#include "./PORT/port.h"
#include "./BSP/DEBUG/debug.h"

// clang-format off
#define ADC_CR1_AWDCH_Pos         (0U)                          

#define ADC_CR1_AWDCH_0           (0x01UL << ADC_CR1_AWDCH_Pos)                 /*!< 0x00000001 */
#define ADC_CR1_AWDCH_1           (0x02UL << ADC_CR1_AWDCH_Pos)                 /*!< 0x00000002 */
#define ADC_CR1_AWDCH_2           (0x04UL << ADC_CR1_AWDCH_Pos)                 /*!< 0x00000004 */
#define ADC_CR1_AWDCH_3           (0x08UL << ADC_CR1_AWDCH_Pos)                 /*!< 0x00000008 */
#define ADC_CR1_AWDCH_4           (0x10UL << ADC_CR1_AWDCH_Pos)                 /*!< 0x00000010 */

#define ADC_CHANNEL_0           0x00000000U
#define ADC_CHANNEL_1           ((uint32_t)ADC_CR1_AWDCH_0)
#define ADC_CHANNEL_2           ((uint32_t)ADC_CR1_AWDCH_1)
#define ADC_CHANNEL_3           ((uint32_t)(ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0))
#define ADC_CHANNEL_4           ((uint32_t)ADC_CR1_AWDCH_2)
#define ADC_CHANNEL_5           ((uint32_t)(ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_0))
#define ADC_CHANNEL_6           ((uint32_t)(ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1))
#define ADC_CHANNEL_7           ((uint32_t)(ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0))
#define ADC_CHANNEL_8           ((uint32_t)ADC_CR1_AWDCH_3)
#define ADC_CHANNEL_9           ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_0))
#define ADC_CHANNEL_10          ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_1))
#define ADC_CHANNEL_11          ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0))
#define ADC_CHANNEL_12          ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2))
#define ADC_CHANNEL_13          ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_0))
#define ADC_CHANNEL_14          ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1))
#define ADC_CHANNEL_15          ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0))
#define ADC_CHANNEL_16          ((uint32_t)ADC_CR1_AWDCH_4)
#define ADC_CHANNEL_17          ((uint32_t)(ADC_CR1_AWDCH_4 | ADC_CR1_AWDCH_0))
#define ADC_CHANNEL_18          ((uint32_t)(ADC_CR1_AWDCH_4 | ADC_CR1_AWDCH_1))

#define ADC_CHANNEL_VREFINT     ((uint32_t)ADC_CHANNEL_17)
#define ADC_CHANNEL_VBAT        ((uint32_t)ADC_CHANNEL_18)

#define ADC_CHANNEL_N 0xFFFF

const uint16_t adc_channel_map[] = // adc1
{
        ADC_CHANNEL_0, ADC_CHANNEL_1, ADC_CHANNEL_2, ADC_CHANNEL_3, ADC_CHANNEL_4, ADC_CHANNEL_5, ADC_CHANNEL_6, ADC_CHANNEL_7,
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, // PA0-PA15
        ADC_CHANNEL_8, ADC_CHANNEL_9, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N,
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, // PB0-PB15
        ADC_CHANNEL_10, ADC_CHANNEL_11, ADC_CHANNEL_12, ADC_CHANNEL_N, ADC_CHANNEL_14, ADC_CHANNEL_15, ADC_CHANNEL_N, ADC_CHANNEL_N,
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_13, ADC_CHANNEL_N, ADC_CHANNEL_N, // PC0-PC15
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N,
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, // PD0-PD15
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N,
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, // PE0-PE15
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N,
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, // PF0-PF15
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N,
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, // PG0-PG15
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N,
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, // PH0-PH15
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N,
        ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, ADC_CHANNEL_N, // PI0-PI15
};
// clang-format on

static uint8_t adc_pin_value_map[16] = {0};
static uint16_t adc_value[16] = {0};
uint8_t adc_regular_rank_cnt = 0;
uint8_t g_adc_dma_sta = 0; /* DMA传输状态标志, 0,未完成; 1, 已完成 */

/**
 * @brief       使能一次ADC DMA传输
 * @param       cndtr: DMA传输的次数
 * @retval      无
 */
static void adc_dma_enable(uint16_t cndtr)
{
    ADC1->CR2 &= ~(1 << 0); /* 先关闭ADC */

    dma_enable(DMA2_Stream4, cndtr); /* 重新使能DMA传输 */

    ADC1->CR2 |= 1 << 0;  /* 重新启动ADC */
    ADC1->CR2 |= 1 << 30; /* 启动规则转换通道 */
}

/**
 * @brief        ADC引脚初始化
 * @param        adc_id: ADC编号
 * @param        pinx: 引脚编号
 * @retval      无
 */
void adc_pin_init(uint8_t adc_id, uint8_t pinx)
{
    ADC_TypeDef *adcx;

	if (adc_id == 2)
	{
        DEBUG_ERROR("ADC2 not support\r\n");
        return;	
	}
	else if (adc_id == 3)
	{
		DEBUG_ERROR("ADC3 not support\r\n");
        return;
	}
	
    if (adc_id == 1)
    {
        adcx = ADC1;
        RCC->APB2ENR |= 1 << 8; // 使能ADC1时钟
    }
    else if (adc_id == 2)
    {
        adcx = ADC2;
        RCC->APB2ENR |= 1 << 9; // 使能ADC2时钟
    }
    else if (adc_id == 3)
    {
        adcx = ADC3;
        RCC->APB2ENR |= 1 << 10; // 使能ADC3时钟
    }

    adc_pin_value_map[adc_regular_rank_cnt] = pinx;
    if (adc_channel_map[pinx] == ADC_CHANNEL_N)
    {
        DEBUG_ERROR("adc pin[%d] not support\r\n", pinx);
        return;
    }
    if (adc_regular_rank_cnt == 0)
    {
        RCC->APB2RSTR |= 1 << 8;    /* ADC1 & ADC2 & ADC3 复位, 注意, 这里复位了所有ADC!!! */
        RCC->APB2RSTR &= ~(1 << 8); /* 复位结束 */

        adcx->CR1 = 0; /* CR1清零 */
        adcx->CR2 = 0; /* CR2清零 */
    }

    ADC->CCR &= ~(3 << 16); /* ADCPRE[1:0] ADC时钟预分频清零 */
    ADC->CCR |= 1 << 16;    /* 设置ADC时钟预分频系数为 4, 即 PCLK2 / 4 = 21Mhz */
    /* 配置ADC连续转换, DMA传输ADC数据 */
    adcx->CR1 |= 1 << 8;  /* SCAN = 1, 扫描模式 */
    adcx->CR1 |= 0 << 24; /* 12位模式 */
    adcx->CR2 |= 1 << 1;  /* CONT = 1, 连续转换模式 */
    adcx->CR2 |= 0 << 11; /* 右对齐 */
    adcx->CR2 |= 0 << 28; /* 软件触发 */

    adcx->CR2 |= 1 << 0; /* 开启AD转换器 */

    /* 设置转换序列 */
    /* 配置ADC连续转换, DMA传输ADC数据 */
    adcx->CR1 |= 1 << 8; /* SCAN = 1, 扫描模式 */
    adcx->CR2 |= 1 << 8; /* DMA = 1, DMA传输使能 */
    adcx->CR2 |= 1 << 9; /* DDS = 1, 只要发生转换就请求DMA */
    adcx->CR2 |= 1 << 1; /* CONT = 1, 连续转换模式 */

    /* DMA基本设置, 数据流/通道/外设地址/存储器地址等 */
    dma_basic_config(DMA2_Stream4, 0, (uint32_t)&adcx->DR, (uint32_t)adc_value, 0);

    DMA2_Stream4->CR |= 0 << 6;  /* 外设到存储器模式 */
    DMA2_Stream4->CR |= 1 << 8;  /* 循环模式 */
    DMA2_Stream4->CR |= 0 << 9;  /* 外设非增量模式 */
    DMA2_Stream4->CR |= 1 << 10; /* 存储器增量模式 */
    DMA2_Stream4->CR |= 1 << 11; /* 外设数据长度:16位 */
    DMA2_Stream4->CR |= 1 << 13; /* 存储器数据长度:16位 */
    DMA2_Stream4->CR |= 1 << 16; /* 中等优先级 */
    DMA2_Stream4->CR |= 0 << 21; /* 外设突发单次传输 */
    DMA2_Stream4->CR |= 0 << 23; /* 存储器突发单次传输 */

    DMA2_Stream4->CR |= 1 << 4; /* TCIE = 1, DMA传输完成中断使能 */

    if (adc_channel_map[pinx] < 10) /* 通道0~9,使用SMPR2配置 */
    {
        adcx->SMPR2 &= ~(3 << (3 * adc_channel_map[pinx])); /* 通道ch 采样时间清空 */
        adcx->SMPR2 |= 3 << (3 * adc_channel_map[pinx]);    /* 通道ch 采样周期设置,周期越高精度越高 */
    }
    else /* 通道10~19,使用SMPR1配置 */
    {
        adcx->SMPR1 &= ~(3 << (3 * (adc_channel_map[pinx] - 10))); /* 通道ch 采样时间清空 */
        adcx->SMPR1 |= 3 << (3 * (adc_channel_map[pinx] - 10));    /* 通道ch 采样周期设置,周期越高精度越高 */
    }

    adcx->SQR1 &= ~(0XF << 20);               /* L[3:0]清零 先清空转换个数设置*/
    adcx->SQR1 |= adc_regular_rank_cnt << 20; /* 设置转换个数*/

    if (adc_regular_rank_cnt < 6)
    {
        adcx->SQR3 |= adc_channel_map[pinx] << (5 * adc_regular_rank_cnt);
    }
    else if (adc_regular_rank_cnt < 12)
    {
        adcx->SQR2 |= adc_channel_map[pinx] << (5 * (adc_regular_rank_cnt - 6));
    }
    else if (adc_regular_rank_cnt < 16)
    {
        adcx->SQR1 |= adc_channel_map[pinx] << (5 * (adc_regular_rank_cnt - 12));
    }

    adc_regular_rank_cnt++;

    /* 其他DMA配置 */

    gpio_pin_init(pinx, GPIO_MODE_AIN, GPIO_OTYPE_PP, GPIO_SPEED_LOW, GPIO_PUPD_NONE);

    adc_dma_enable(adc_regular_rank_cnt);
}



/**
 * @brief        获取ADC值
 * @param        pinx: 引脚编号
 * @retval      无
 */
uint16_t adc_get_value(uint8_t pinx)
{
    for (uint8_t i = 0; i < adc_regular_rank_cnt; i++)
    {
        if (adc_pin_value_map[i] == pinx)
            return adc_value[i];
    }
    return 0xFF;
}
